﻿/*
 * BitmapBlock
 * 
 * Copyright (c) Adam Sida, asida@centrum.cz
 * 
 * All rights reserved.
 */
using System;
using System.IO;
//using System.Drawing;
//using System.Drawing.Imaging;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Petra.Gis.Geometry.Image.Tiff;
using System.Collections.Generic;



namespace Petra.Gis.Geometry.Image
{

  /// <summary>
  /// represents block that is organized as standard bitmap
  /// where each color band alters others eg. RGBRGBRGB....
  /// </summary>
  public class ContigousBitmapBlock : BitmapBlock
  {

    private long _sampleBlockOffset; //pointer to sample block on disk, this BitmapBlock will read single block

    

    #region constructors

    /// <summary>
    /// basic constructor, creates ContigousBitmapBlock from dimensions only
    /// </summary>
    /// <param name="bounds">block position and size</param>
    /// <param name="PixelFormat">format of pixel for this block</param>
    public ContigousBitmapBlock(BlockBitmapSource parentBitmap, Int32Rect bounds, TiffMetadata metadata)
      : base(parentBitmap, bounds, metadata) { }


    /// <summary>
    /// creates ContigousBitmapBlock from existing bitmap
    /// </summary>
    /// <param name="sourceBmp"></param>
    /// <param name="areaOfInterest"></param>
    public ContigousBitmapBlock(BlockBitmapSource parent, BitmapSource sourceBmp, Int32Rect areaOfInterest, TiffMetadata metadata, BitmapOperationType oType)
      : base(parent, sourceBmp, areaOfInterest,metadata, oType) { }




    internal ContigousBitmapBlock(BlockBitmapFrame parent, Int32Rect bounds, TiffReader sourceData, TiffMetadata metadata, long sampleBlockOffset)
      : base(parent, bounds, metadata)
    {

      _sampleBlockOffset = sampleBlockOffset;
    }



    public ContigousBitmapBlock(BlockBitmapSource parent, Int32Rect bounds, TiffMetadata metadata, long sampleBlockOffset)
      : base(parent, bounds, metadata)
    {
      _sampleBlockOffset = sampleBlockOffset;

    }

    #endregion constructors

    #region public members



    /// <summary>
    /// this will load data from image into block
    /// decompress if needed
    /// convert color schema if needed
    /// </summary>
    private BitmapSource loadData()
    {
      byte[] rawDecompressedData;

      //decompress stream data as byte[]
      ((BlockBitmapFrame)_parent).Decoder.TiffReader.BaseStream.Seek(_metadata.BlockOffsets[_sampleBlockOffset], SeekOrigin.Begin);
      rawDecompressedData = ((BlockBitmapFrame)_parent).Compression.DecompressBlock(this, ((BlockBitmapFrame)_parent).Decoder.TiffReader.ReadBytes(_metadata.BlockLengths[_sampleBlockOffset]), _metadata.BitsPerSamples[0]);
      //covert to windows native Rgb24...
      BitmapSource data;
      List<Color>tmpColorList;
    
      if(_metadata.PixelFormat == TiffPixelFormats.Bilevel1bpp && ((BlockBitmapFrame)_parent).Decoder.LoadBitonalAsPaletted8bpp)
      {
        tmpColorList = new List<Color>();
        tmpColorList.Add(Color.FromRgb(0,0,0));
        tmpColorList.Add(Color.FromRgb(255,255,255));
        data = BitmapSource.Create(_bounds.Width, _bounds.Height,600,600,PixelFormats.Indexed8, new BitmapPalette(tmpColorList), rawDecompressedData, BitmapBlock.GetStrideLenght(_bounds.Width, 8));
      }
      else if(_metadata.PixelFormat == TiffPixelFormats.Palette8bpp)
      {
        data = BitmapSource.Create(_bounds.Width, _bounds.Height, 600, 600, PixelFormats.Indexed8, new BitmapPalette(_metadata.ColorMap), rawDecompressedData, BitmapBlock.GetStrideLenght(_bounds.Width, 8));
      }
      else
      {
        byte[] colorConvertedData = TiffColorSpaceConverter.Convert(this, _metadata.PixelFormat, PixelFormats.Rgb24);
        data = BitmapSource.Create(_bounds.Width, _bounds.Height, 600, 600, PixelFormats.Rgb24, null, colorConvertedData, BitmapBlock.GetStrideLenght(_bounds.Width, PixelFormats.Rgb24.BitsPerPixel));
      }

      return data;
    }




    ///// <summary>
    ///// returns (compressed) size of current stripe or tile in bytes
    ///// </summary>
    //public int CompressedSize
    //{
    //  get 
    //  {
    //    if (_image.Metadata.IsTiled)
    //      return System.Convert.ToInt32(_image.Metadata.Ifd.GetTag(Tag.TagId.TILEBYTECOUNTS).TagData[_blockIndex]);
    //    else
    //      return System.Convert.ToInt32(_image.Metadata.Ifd.GetTag(Tag.TagId.STRIPBYTECOUNTS).TagData[_blockIndex]);
    //  }
    //}


    #endregion public members



  }
}
